package modele.entites;
import java.util.ArrayList;
import java.util.List;
import vues.IHM;
import modele.Couple;
import modele.PathFinder;
import modele.map.Case;

public abstract class Bot extends MapEntite {
	
	

	private static final long serialVersionUID = 1L;
	private Feu feuAssigne;
//	private int distance;
	private int[] coordonnee;
	private Orientation orientation;
	private String nom;
	private PathFinder pathFinder;
	private EtatBot etat;
	private boolean arriverFeu; 

	private IHM ihm;

	public Bot(String nom, IHM ihm, PathFinder pathfinder) {
		this.nom = nom;
		this.ihm = ihm;
		
		this.orientation = Orientation.NORD;
		this.pathFinder = pathfinder;
		
		this.etat = EtatBot.ARRET;
	}

	// Calcul la distance du robot au feu
	public void getCalculFeu(Feu f) {
		int[] coordonnee = calculerDistance(this.getCaseCourante(), f.getCaseCourante()); 
//		this.distance = (int)Math.sqrt(Math.pow(Math.abs(coordonnee[0]), 2) + Math.pow(Math.abs(coordonnee[1]), 2));
		this.coordonnee = coordonnee;
	}
	
	public boolean isFeuAssigne() {
        return this.feuAssigne != null;
    }
	
	public Feu getFeuAssigne() {
		return this.feuAssigne;
	}

	public void setFeuAssigne(Feu f) {
		this.feuAssigne = f;
	}
	
	private boolean isArriverFeu() {
		return this.arriverFeu;
	}

//	public int getDistance(){
//		return this.distance;
//	}
	
	public int[] getCoordonnee() {
		return this.coordonnee;
	}
	
	public void setCoordonnee(int[] coordonnee) {
		this.coordonnee = coordonnee;
	}

	public void setEtat(EtatBot etat) {
		this.etat = etat;
	}

	public int[] getDistanceAParcourir(){
		return this.coordonnee;
	}
	
	public String getNom(){
		return this.nom;
	}

	
	public Orientation getOrientation(){
		return this.orientation;
	}
	
	public void setOrientation(Orientation o){
		this.orientation = o;
	}
	
	public String getOrientationImage(){
		String retour = "";
		switch(this.orientation)
		{
		case NORD:
			retour = "haut";
			break;
		case SUD:
			retour = "bas";
			break;
		case EST:
			retour = "droite";
			break;
		case OUEST:
			retour = "gauche";
			break;
		case NORD_OUEST:
			retour = "haut-gauche";
			break;
		case SUD_OUEST:
			retour = "bas-gauche";
			break;
		case NORD_EST:
			retour = "haut-droite";
			break;
		case SUD_EST:
			retour = "bas-droite";
			break;
		}
		return retour;
	}
	
	public void miseAJour(){
		this.etatBot();
	}
	
	public void etatBot(){
		switch(this.etat){
		case ARRET : 
				if(isFeuAssigne()){
					this.etat = EtatBot.DEPLACEMENT;
				}
			break;
		case DEPLACEMENT :
				if(getFeuAssigne().isFeuEteint()){
					this.setFeuAssigne(null);
					this.etat = EtatBot.ARRET;
					this.arriverFeu = false;
				}else if(this.isArriverFeu()){
					this.etat = EtatBot.EXTINCTION;
				}else{
					this.deplacement();
				}
			break;
		case EXTINCTION:
			if(getFeuAssigne().isFeuEteint()){
				this.setFeuAssigne(null);
				this.etat = EtatBot.ARRET;
				this.arriverFeu = false;
			}else{
				this.eteindreFeu();
			}
			break;
		}
		this.ihm.refresh();
		
	}

	private void eteindreFeu() {
		this.getFeuAssigne().decrementerIntensite();
		if(this.getFeuAssigne().getIntensite() == 0){
			this.getFeuAssigne().setEtat(false);
			this.getFeuAssigne().setFeuEnExtinction(false);
			this.arriverFeu = false;
		}
		
	}

	public EtatBot getEtat() {
		return etat;
	}

	private void deplacement() {
		int [] distanceAParcourir= this.getDistanceAParcourir();
		if((distanceAParcourir[0] == -1 && distanceAParcourir[1]== -1) 
				|| (distanceAParcourir[0] == 1 && distanceAParcourir[1]== 1)
					|| (distanceAParcourir[0] == -1 && distanceAParcourir[1]== 1)
						|| (distanceAParcourir[0] == 1 && distanceAParcourir[1]== -1)){
			this.arriverFeu = true;
		} else if(distanceAParcourir[0] == 0){
			// Avance de 1 ou de -1 case sur l'axe des Y --------> Verticalement
			if(distanceAParcourir[1]<-1){
				distanceAParcourir[1]+=1;
				this.setCaseCourante(this.ihm.getHorloge().getSimulateur().getMap().getCase(this.getCaseCourante().getX(), this.getCaseCourante().getY()+1));
				this.setOrientation(Orientation.SUD);
			}else if(distanceAParcourir[1]>1 ){
				distanceAParcourir[1]-=1;
				this.setCaseCourante(this.ihm.getHorloge().getSimulateur().getMap().getCase(this.getCaseCourante().getX(), this.getCaseCourante().getY()-1));
				this.setOrientation(Orientation.NORD);
			}else{
				this.arriverFeu = true;
			}
		}else if(distanceAParcourir[1] == 0){
			//Avance de 1 ou de -1 sur l'axe des X  --------> Horizontalement
			if(distanceAParcourir[0]<-1){
				distanceAParcourir[0]+=1;
				this.setOrientation(Orientation.EST);
				this.setCaseCourante(this.ihm.getHorloge().getSimulateur().getMap().getCase(this.getCaseCourante().getX()+1, this.getCaseCourante().getY()));
			}else if(distanceAParcourir[0]>1){
				distanceAParcourir[0]-=1;
				this.setCaseCourante(this.ihm.getHorloge().getSimulateur().getMap().getCase(this.getCaseCourante().getX()-1, this.getCaseCourante().getY()));
				this.setOrientation(Orientation.OUEST);
			}else{
				this.arriverFeu = true;
			}
		}else if(distanceAParcourir[0] != 0 && distanceAParcourir[1]!= 0){
			// Avance de 1 ou de -1 sur l'axe des X et sur l'axe des Y  --------> En diagonal
			if(distanceAParcourir[0]<0){
				distanceAParcourir[0]+=1;
				this.setOrientation(Orientation.EST);
				this.setCaseCourante(this.ihm.getHorloge().getSimulateur().getMap().getCase(this.getCaseCourante().getX()+1, this.getCaseCourante().getY()));
			}else if(distanceAParcourir[0]>0){
				distanceAParcourir[0]-=1;
				this.setCaseCourante(this.ihm.getHorloge().getSimulateur().getMap().getCase(this.getCaseCourante().getX()-1, this.getCaseCourante().getY()));
				this.setOrientation(Orientation.OUEST);
			}
			if(distanceAParcourir[1]<0){
				distanceAParcourir[1]+=1;
				this.setCaseCourante(this.ihm.getHorloge().getSimulateur().getMap().getCase(this.getCaseCourante().getX(), this.getCaseCourante().getY()+1));
				if (this.getOrientation() == Orientation.OUEST)
					this.setOrientation(Orientation.SUD_OUEST);
				else
					this.setOrientation(Orientation.SUD_EST);
			}else if(distanceAParcourir[1]>0 ){
				distanceAParcourir[1]-=1;
				this.setCaseCourante(this.ihm.getHorloge().getSimulateur().getMap().getCase(this.getCaseCourante().getX(), this.getCaseCourante().getY()-1));
				if (this.getOrientation() == Orientation.OUEST)
					this.setOrientation(Orientation.NORD_OUEST);
				else
					this.setOrientation(Orientation.NORD_EST);
				
			}
		}else{
			this.arriverFeu = true;
		}
		
	}

	public Couple getListePlusCourtDistanceEntites(modele.map.Map map, List<Couple> listeFeu) {
		
		int nbFeux = listeFeu.size();
		int[] distancesChemin = new int[nbFeux];
		int i = 0;
		int robot = 0;
		List<Case> cheminPathfinding;
		
		for(Couple c : listeFeu){
			if((Integer)c.getSecond()==robot){
				cheminPathfinding = pathFinder.pathfinding(map, this.getCaseCourante(), ((Feu)c.getPremier()).getCaseCourante());
				distancesChemin[i] = Case.getCoutChemin(cheminPathfinding.subList(0, cheminPathfinding.size()-1));
				i++;
			}else{
				robot++;
			}
		}
		
		Integer distanceMini = new Integer(distancesChemin[0]);
		MapEntite feuMini = ((Feu)listeFeu.get(0).getPremier());
		for(int j = 1 ; j < nbFeux ; j++) {
			if(distancesChemin[j] <= distanceMini) {
				distanceMini = distancesChemin[j];
				feuMini = ((Feu)listeFeu.get(j).getPremier());
			}
		}
			
		return new Couple(feuMini, distanceMini);
	}
}